package com.tool.common.datastructure;

/**
 * 循环队列.
 *
 * @author: 20231
 */
public class CircleIntQueue {

    /**
     * 保存数据.
     */
    private final int[] data;

    /**
     * 数组大小.
     */
    private final int size;

    /**
     * 头部位置.
     */
    private int head;

    /**
     * 尾部的位置.
     */
    private int tail;

    /**
     * 队列是否满了
     */
    private boolean full;

    public CircleIntQueue(int size) {
        data = new int[size];
        this.size = size;
        this.head = 0;
        this.tail = 0;
    }

    /**
     * 入列，将数据加到循环队列的最后一位，当队列满时，直接覆盖
     *
     * @param val 数据
     */
    public void enqueue(int val) {
        data[tail] = val;

        // 尾部向后移动一位
        tail = (tail + 1) % size;

        if (full) {
            head = (head + 1) % size;
        }

        // 如果存入一位后尾部大于队列长度，则表示队列满了, 需要将头部向后移动一位.
        if (!full && (tail + size - head) % size == 0) {
            full = true;
        }
    }

    /**
     * 获取队列中的一个数.
     *
     * @return 获取的数
     */
    public int dequeue() {
        int realSize = getRealSize();
        if (realSize == 0) {
            throw new RuntimeException();
        }

        int rtn = data[head];
        head = (head + 1) % size;

        return rtn;
    }

    /**
     * 计算平均数.
     *
     * @return 平均数
     */
    public float average() {
        int realSize = getRealSize();

        int total = 0;
        for (int i = 0; i < realSize; i++) {
            total += data[(head + i) % size];
        }

        return (float) total / realSize;
    }

    /**
     * 获取队列真实的大小.
     *
     * @return 真实大小
     */
    private int getRealSize() {
        return full ? size : (tail + size - head) % size;
    }

    @Override
    public String toString() {
        int realSize = getRealSize();

        StringBuilder sb = new StringBuilder("[");
        for (int i = 0; i < realSize; i++) {

            if (i != 0) {
                sb.append(" ,");
            }

            int index = (head + i) % size;
            sb.append(data[index]);
        }

        return sb.append("]").toString();
    }

    public static void main(String[] args) {
        CircleIntQueue circleIntQueue = new CircleIntQueue(4);

        for (int i = 0; i < 10; i++) {
            circleIntQueue.enqueue(i);
            System.out.println(i + " : " + circleIntQueue + " : " + circleIntQueue.average());
        }
    }
}
